%% copy riak-0.14.2 source to learn dynamo implementation and erlang
%% author: lichuang
%% copy source from riak_core_bucket.erl

-module(edynamo_bucket).
-export([get_bucket/1,
         get_bucket/2,
         append_bucket_defaults/1,
         set_bucket/2]).

%% @spec get_bucket(edynamo_object:bucket()) ->
%%         {ok, BucketProps :: edynamo_bucketprops()}
%% @doc Return the complete current list of properties for Bucket.
%% Properties include but are not limited to:
%% <pre>
%% n_val: how many replicas of objects in this bucket (default: 3)
%% allow_mult: can objects in this bucket have siblings? (default: false)
%% linkfun: a function returning a m/r FunTerm for link extraction
%% </pre>
%%
get_bucket(Name) ->
  {ok, Ring} = edynamo_ring_manager:get_my_ring(),
  get_bucket(Name, Ring).

%% @spec get_bucket(Name, Ring:edynamo_ring:edynamo_ring()) ->
%%          BucketProps :: edynamo_bucketprops()
%% @private
get_bucket(Name, Ring) ->
  case edynamo_ring:get_meta({bucket, Name}, Ring) of
    undefined ->
      [{name, Name}
       | app_helper:get_env(edynamo, default_bucket_props)];
   {ok, Bucket} ->
     Bucket
  end.

%% @doc Add a list of defaults to global list of defaults for new buckets.
append_bucket_defaults(Items) when is_list(Items) ->
  NewDefaults = app_helper:get_env(edynamo, default_bucket_props) ++ Items,
  application:set_env(edynamo, default_bucket_props, NewDefaults).

%% @spec set_bucket(edynamo_object:bucket(), BucketProps::edynamo_bucketprops()) -> ok
%% @doc Set the given BucketProps in Bucket.
set_bucket(Name, BucketProps) ->
  F = fun(Ring, _Args) ->
        OldBucket = get_bucket(Name),
        NewKeys = proplists:get_keys(BucketProps),
        PrunedOld = [{K, V} || {K, V} <- OldBucket,
                                not lists:member(K, NewKeys)],
        {new_ring, edynamo_ring:update_meta({bucket, Name},
                                            BucketProps ++ PrunedOld,
                                            Ring)}
      end,
  edynamo_ring_manager:ring_trans(F, undefined),
  edynamo_ring_manager:write_ringfile(),
  ok.
